package Mi

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"gitee.com/tools/internal/domain"
	"gitee.com/tools/internal/service/IP"
	"io"
	"log"
	"net/http"
	"strings"
	"sync"
	"time"
)

type MIService struct {
	apiIp     string
	apiPhone  string
	apiCode   string
	apiDns    string
	apiDomain string
	lock      sync.Mutex
}

func (m *MIService) QueryDomainWeight(ctx context.Context, d string) (domain.DomainWeight, error) {
	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
	defer cancel()
	m.lock.Lock()
	defer m.lock.Unlock()
	apiPath := fmt.Sprintf("%s?domain=%s&type=%s", m.apiDomain, d, "json")
	resp, err := http.Get(apiPath)
	if err != nil {
		return domain.DomainWeight{}, err
	}
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return domain.DomainWeight{}, err
	}
	defer resp.Body.Close()
	if resp.StatusCode > 299 || resp.StatusCode != 200 {
		err = fmt.Errorf("Response failed with status code: %d and\nbody: %s\n", resp.StatusCode, body)
		log.Println(err)
		return domain.DomainWeight{}, err
	}

	bodystr := string(body)
	type Resp struct {
		Code int                 `json:"code"`
		Msg  string              `json:"msg"`
		Data domain.DomainWeight `json:"data"`
	}
	//对返回的json数据做解析
	var datajson Resp
	err = json.Unmarshal([]byte(bodystr), &datajson)
	select {
	case <-ctx.Done():
		return domain.DomainWeight{}, errors.New("查询超时")
	default:
		return datajson.Data, err
	}
}

func (m *MIService) QueryDns(ctx context.Context, data domain.Dns) (string, error) {
	ctx, cancel := context.WithTimeout(ctx, time.Second*1)
	defer cancel()
	m.lock.Lock()
	defer m.lock.Unlock()
	apiPath := fmt.Sprintf("%s?domain=%s&type=%s&only=%s", m.apiDns, data.Domain, data.Type, data.Only)
	resp, err := http.Get(apiPath)
	if err != nil {
		return "", err
	}
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	if resp.StatusCode > 299 || resp.StatusCode != 200 {
		err = fmt.Errorf("Response failed with status code: %d and\nbody: %s\n", resp.StatusCode, body)
		log.Println(err)
		return "", err
	}

	bodystr := string(body)

	select {
	case <-ctx.Done():
		return "", errors.New("查询超时")
	default:
		return bodystr, err
	}
}
func (m *MIService) QueryCountryCode(ctx context.Context, words string, t string) (domain.CountryCode, error) {
	ctx, cancel := context.WithTimeout(ctx, time.Second*1)
	defer cancel()
	m.lock.Lock()
	defer m.lock.Unlock()
	apiPath := fmt.Sprintf("%s?cc=%s&type=%s", m.apiCode, words, t)
	var info = domain.CountryCode{}
	resp, err := http.Get(apiPath)
	if err != nil {
		return info, err
	}
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return info, err
	}
	defer resp.Body.Close()
	if resp.StatusCode > 299 || resp.StatusCode != 200 {
		err = fmt.Errorf("Response failed with status code: %d and\nbody: %s\n", resp.StatusCode, body)
		log.Println(err)
		return info, err
	}

	bodystr := string(body)
	if !strings.Contains(bodystr, "200") {
		return info, errors.New("其他原因")
	}
	type Resp struct {
		Code int                `json:"code"`
		Msg  string             `json:"msg"`
		Data domain.CountryCode `json:"data"`
	}
	//对返回的json数据做解析
	var datajson Resp
	err = json.Unmarshal([]byte(bodystr), &datajson)
	select {
	case <-ctx.Done():
		return domain.CountryCode{}, errors.New("查询超时")
	default:
		return datajson.Data, err
	}
}

func (m *MIService) QueryPhone(ctx context.Context, mobile string, status string) (domain.MPhone, error) {
	ctx, cancel := context.WithTimeout(ctx, time.Second*1)
	defer cancel()
	m.lock.Lock()
	defer m.lock.Unlock()
	apiPath := fmt.Sprintf("%s?mobile=%s&saorao=%s", m.apiPhone, mobile, status)
	var info = domain.MPhone{}
	resp, err := http.Get(apiPath)
	if err != nil {
		return info, err
	}
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return info, err
	}
	defer resp.Body.Close()
	if resp.StatusCode > 299 || resp.StatusCode != 200 {
		err = fmt.Errorf("Response failed with status code: %d and\nbody: %s\n", resp.StatusCode, body)
		log.Println(err)
		return info, err
	}

	bodystr := string(body)
	if !strings.Contains(bodystr, "200") {
		return info, errors.New("其他原因")
	}
	type Resp struct {
		Code int           `json:"code"`
		Msg  string        `json:"msg"`
		Data domain.MPhone `json:"data"`
	}
	//对返回的json数据做解析
	var datajson Resp
	err = json.Unmarshal([]byte(bodystr), &datajson)
	return datajson.Data, err
}

func (m *MIService) QueryIp(ctx context.Context, ip string) (domain.IpInfo, error) {
	ctx, cancel := context.WithTimeout(ctx, time.Second*1)
	defer cancel()
	m.lock.Lock()
	defer m.lock.Unlock()
	apiPath := fmt.Sprintf("%s?ip=%s&type=%s", m.apiIp, ip, "json")
	var info = domain.IpInfo{}
	resp, err := http.Get(apiPath)
	if err != nil {
		return info, err
	}
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return info, err
	}
	defer resp.Body.Close()
	if resp.StatusCode > 299 || resp.StatusCode != 200 {
		err = fmt.Errorf("Response failed with status code: %d and\nbody: %s\n", resp.StatusCode, body)
		log.Println(err)
		return info, err
	}

	bodystr := string(body)
	if !strings.Contains(bodystr, "200") {
		log.Println("IP错误或者其他原因")
		return info, errors.New("IP错误或者其他原因")
	}
	type Resp struct {
		Code int             `json:"code"`
		Msg  string          `json:"msg"`
		Data domain.IpInfoms `json:"data"`
	}
	//对返回的json数据做解析
	var datajson Resp

	err = json.Unmarshal([]byte(bodystr), &datajson)
	info = m.ToIpInfo(datajson.Data)
	return info, err
}
func (i *MIService) ToIpInfo(infos domain.IpInfoms) domain.IpInfo {
	return domain.IpInfo{
		AreaCode:    infos.AreaCode,
		Dec:         infos.Dec,
		City:        infos.City,
		Country:     infos.Country,
		CountryCode: infos.CountryCode,
		District:    infos.District,
		Ip:          infos.Ip,
		Idc:         infos.Idc,
		Isp:         infos.Isp,
		Net:         infos.Net,
		Protocol:    infos.Protocol,
		Location:    infos.Location,
		Myip:        infos.Myip,
		Time:        infos.Time,
		Province:    infos.Province,
		ZipCode:     infos.ZipCode,
	}
}
func NewMiService() IP.Ip {
	return &MIService{
		apiIp:     "https://api.mir6.com/api/ip",
		apiPhone:  "https://api.mir6.com/api/mobile",
		apiCode:   "https://api.mir6.com/api/gjdm",
		apiDns:    "https://api.mir6.com/api/dns",
		apiDomain: "https://api.mir6.com/api/bdqz",
	}
}
